import {celebrate, Joi} from "celebrate";
import * as config from 'config'
import {withLock} from "easylock";
import {Request, Router} from "express";
import {v4 as uuid} from "node-uuid";
import * as request from 'superagent'
import GlobalModel from "../database/models/global";
import {PlayerModel} from "../database/models/player";
import {RechargeWithOtherGameModel} from "../database/models/rechargeWithOtherGame";
import {RechargeWithOtherGameOrderModel} from "../database/models/rechargeWithOtherGameOrder";
import {InternalError} from "./error";
import {jwtSign} from "./jwt";
import {Response, withUser} from "./middlewareType"
import {jwtAuthMiddleware} from "./passort";
import {freeCoinDefault, pcUrl} from "./utils";
import {wechatAuth} from "./wechatAuth";

const router = Router()

const initGold = config.get<number>("game.initModelGoldCount")

router.post('/wechat',
  celebrate({
    body: Joi.object().keys({
      code: Joi.string().required()
    }).required()
  }), async (req, res: Response) => {
    try {
      const authInfo = await wechatAuth.getAuthInfo(req.body.code)
      const userInfo = await wechatAuth.getUserInfo(authInfo)

      await withLock(userInfo.openid, async () => {
        let playerModel = await PlayerModel.findOne({wechatUnionid: userInfo.unionid})
        if (playerModel) {
          playerModel.wechatBind = authInfo,
            playerModel.wechatOpenId = userInfo.openid,
            playerModel.cookie = uuid()
          await playerModel.save()
        } else {
          const updater = {$inc: {shortIdCounter: 1}}
          const options = {new: true}
          const global = await GlobalModel.findOneAndUpdate({}, updater, options)
          const shortId = global.shortIdCounter;

          const player = {
            name: userInfo.nickname,
            wechatOpenId: userInfo.openid,
            wechatUnionid: userInfo.unionid,
            gem: 0,
            headImgUrl: userInfo.headimgurl,
            sex: userInfo.sex,
            gold: initGold,
            freeCoin: freeCoinDefault,
            shortId,
            isTourist: false,
            cookie: uuid(),
            wechatBind: authInfo
          }
          playerModel = await PlayerModel.create(player)
        }

        const token = jwtSign({
          _id: playerModel.id, cookie: playerModel.cookie
        })

        res.json({
          ok: true, data: {
            player: playerModel,
            token
          }
        })

      })
    } catch (e) {
      res.error(e)
    }
  }
)

router.get('/getPCPlayerInfo',
  jwtAuthMiddleware,
  async (req: Request & withUser, res) => {
    const player = await PlayerModel.findById(req.user.id)
    const wechatUnionid = player.wechatUnionid
    if (!wechatUnionid) {
      return res.json({
        ok: false, data: {
          info: '获取用户信息失败！'
        }
      })
    }
    request.get(pcUrl + '/provideForOtherGame/getPlayerInfo/' + wechatUnionid)
      .end((e, r) => {
        if (e || !r.body.ok) {
          return res.json({
            ok: false,
            data: {
              info: '查找失败！'
            }
          })
        }
        res.json({
          ok: true, data: {gem: r.body.data.gem, shortId: r.body.data.shortId}
        })
      })
  })

router.post('/pcLogin',
  celebrate({
    body: Joi.object().keys({
      playerId: Joi.string().required(),
      headImgUrl: Joi.string().default(''),
      name: Joi.string().default(''),
      sex: Joi.number().default(1)
    }).required()
  }),
  async (req, res) => {
    const playerId = req.body.playerId
    const headImgUrl = req.body.headImgUrl || ''
    const name = req.body.name || ''
    const sex = req.body.sex || ''
    let model = await PlayerModel.findOne({wechatUnionid: playerId})

    if (!model) {
      const result = await request.post(pcUrl + '/provideForOtherGame/findOrCreatePlayer')
        .send({playerId, headImgUrl, name, sex})
        .then(r => {

          if (r.body.ok) {
            return r.body
          } else {
            return {ok: false}
          }
        }).catch(e => {
          console.error('gm-dev login err ', e)
          return {ok: false}
        })

      if (!result.ok) {
        return res.json({
          ok: false, data: {
            info: '获取数据失败！'
          }
        })
      }
      const updater = {$inc: {shortIdCounter: 1}}
      const options = {new: true}
      const global = await GlobalModel.findOneAndUpdate({}, updater, options)
      const shortId = global.shortIdCounter;

      const getData = result.data
      const player = {
        wechatUnionid: getData._id,
        name: getData.name || shortId,
        gem: 0,
        headImgUrl: getData.headImgUrl || '',
        sex: getData.sex || 0,
        phone: getData.phone,
        freeCoin: freeCoinDefault,
        shortId,
        freeGold: 0,
        isTourist: false,
        cookie: uuid()
      }
      model = await PlayerModel.create(player)
    }

    if (!model) {
      return res.json({
        ok: false, data: {
          info: '获取数据失败！'
        }
      })
    }

    const token = jwtSign({
      _id: model.id, cookie: model.cookie
    })

    res.json({
      ok: true, data: {
        player: model,
        token
      }
    })
  })

router.get('/pcRechargeList',
  jwtAuthMiddleware,
  async (req, res) => {
    // await RechargeWithOtherGameModel.create({
    //   type:'pc',
    //   otherMoney: 1,
    //   coin: 6,
    //   state: 'on'
    // })
    const rechargeList = await RechargeWithOtherGameModel.find({state: 'on'})
    res.json({
      ok: true,
      data: {
        rechargeList
      }
    })
  })

router.get('/pcRecgarge/:rechargeId',
  jwtAuthMiddleware,
  celebrate({
    params: Joi.object().keys({
      rechargeId: Joi.string().required()
    })
  }),
  async (req: Request & withUser, res) => {
    const rechargeData = await RechargeWithOtherGameModel.findById(req.params.rechargeId)
    if (!rechargeData) {
      return res.json({
        ok: false,
        data: {
          info: '错误请求！'
        }
      })
    }


    const rechargeOrder = await RechargeWithOtherGameOrderModel.create({
      player: req.user.id,
      otherMoney: rechargeData.otherMoney,
      coin: rechargeData.coin,
      freeCoin: rechargeData.freeCoin,
      gem: rechargeData.gem,
      type: 'exchange',
      state: 'unpaid',
      createAt: new Date(Date.now())
    })

    const player = await PlayerModel.findById(req.user.id)

    request.post(pcUrl + '/provideForOtherGame/recharge')
      .send({
        rechargeOrderId: rechargeOrder._id,
        gem: rechargeOrder.otherMoney,
        type: rechargeOrder.type,
        wechatUnionid: player.wechatUnionid,
        gameType: ''
      })
      .end(async (err, r) => {

        if (err) {
          res.json({
            ok: false,
            data: {
              info: '兑换失败！'
            }
          })
          console.error('gm-dev login err ', err)
          return
        }

        if (r.body.ok) {
          rechargeOrder.finishAt = new Date(Date.now())
          rechargeOrder.state = 'paid'
          await rechargeOrder.save()

          player.gem += rechargeOrder.gem || 0
          await player.save()
          res.json({
            ok: true,
            data: {
              info: '兑换成功！'
            }
          })
        } else {
          res.json({
            ok: false,
            data: {
              info: '兑换失败！'
            }
          })
        }
      })
  })

router.post('/bind/wechat',
  jwtAuthMiddleware,
  celebrate({
    body: Joi.object().keys({
      code: Joi.string().required()
    }).required()
  }),
  async (req: Request & withUser, res: Response) => {

    if (req.user.wechatBind) {
      res.error(InternalError('ALREADY_BOUND_WECHAT_ACCOUNT'))
    } else {

      try {
        await withLock(req.user.id, async () => {

          const player = await PlayerModel.findById(req.user.id)

          const authInfo = await wechatAuth.getAuthInfo(req.body.code)
          const userInfo = await wechatAuth.getUserInfo(authInfo)

          player.wechatOpenId = userInfo.openid
          player.wechatBind = authInfo

          await player.save()

          res.json({
            ok: true
          })

        })
      } catch (e) {
        res.error(e)
      }
    }
  })

export default router
